package cz.proks.simplecalendarmanager.server.servlet;

import java.util.logging.Level;
import java.util.logging.Logger;


import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;
import com.google.gdata.client.authn.oauth.GoogleOAuthHelper;
import com.google.gdata.client.authn.oauth.GoogleOAuthParameters;
import com.google.gdata.client.authn.oauth.OAuthException;
import com.google.gdata.client.authn.oauth.OAuthHmacSha1Signer;
import com.google.gwt.user.client.rpc.InvocationException;

import cz.proks.simplecalendarmanager.client.exception.NoAccessException;
import cz.proks.simplecalendarmanager.client.exception.UserNotLoggedException;
import cz.proks.simplecalendarmanager.client.service.OAuthService;
import cz.proks.simplecalendarmanager.server.Configuration;
import cz.proks.simplecalendarmanager.shared.ClientConstants;
import cz.proks.simplecalendarmanager.shared.model.AccessToken;

public class OAuthServiceImpl extends SCMRemoteServiceServlet implements OAuthService {
	private final static Logger log = Logger.getLogger(OAuthServiceImpl.class.getSimpleName());		
		
	private boolean hasAccess(ClientConstants.AppScope scope) {
		return getAccessTokenFromSession(scope.getIdentifier()) != null;
	}

	@Override
	public void checkAccess(ClientConstants.AppScope scope) throws UserNotLoggedException, NoAccessException {
		log.info("checkAccess():: start");
		
		if (hasAccess(scope)) {
			log.info("checkAccess():: granted");
			return;
		}
		
		try {
			UserService userService = UserServiceFactory.getUserService();							
			
			if (!userService.isUserLoggedIn()) {
				log.info("checkAccess():: user not logged");
				throw new UserNotLoggedException(userService.createLoginURL(Configuration.getHomeUrl()));
			} else {			
				String callbackUrl = Configuration.getHomeUrl() + "/oauthAccess" + "?appScope=" + scope.getIdentifier();
				
				GoogleOAuthParameters oauthParameters = new GoogleOAuthParameters();
				oauthParameters.setOAuthConsumerKey(Configuration.getConsumerToken());
				oauthParameters.setOAuthConsumerSecret(Configuration.getConsumerTokenSecret());			
				oauthParameters.setOAuthCallback(callbackUrl);
				oauthParameters.setScope(scope.getUrl());				
				
				GoogleOAuthHelper oauthHelper = new GoogleOAuthHelper(new OAuthHmacSha1Signer());
				oauthHelper.getUnauthorizedRequestToken(oauthParameters);
				
				AccessToken accessToken = new AccessToken(oauthParameters.getOAuthToken(), oauthParameters.getOAuthTokenSecret());
				setAccessTokenToSession(scope.getIdentifier(), accessToken);
				
				String authorizationUrl = oauthHelper.createUserAuthorizationUrl(oauthParameters);			
												
				log.info("checkAccess():: created authorization url");
				throw new NoAccessException(authorizationUrl);
			}
		} catch (OAuthException oaex) {
			log.log(Level.WARNING, "checkAccess()::", oaex);
			throw new InvocationException("", oaex);
		}		
	}	
}
